<template>
    <div class="dom-to-img">
        <div class="dti-card" @click="handleClick">
            <img
                src="https://p.qqan.com/up/2022-8/2022815141509020.jpg"
                alt=""
            />
            <div class="dti-title">这是标题呀</div>
            <div class="dti-content">这下面可及时描述信息了</div>
        </div>
    </div>
</template>
<script setup lang="ts">
// DOM转图片的方法
var domToImg = (function () {
    // 转png需要的canvas对象及其上下文
    var canvas = document.createElement('canvas')
    var context = canvas.getContext('2d')

    // canvas绘制图片元素方法
    var draw = function (img: HTMLImageElement) {
        if (!context) return
        var width = img.width,
            height = img.height
        // canvas绘制
        canvas.width = width
        canvas.height = height
        // 画布清除
        context.clearRect(0, 0, width, height)
        // 绘制图片到canvas
        context.drawImage(img, 0, 0)
    }

    // canvas画布绘制的原图片
    var img = new Image()
    // 回调
    var callback = function () {}

    // 图片回调
    img.onload = function () {
        draw(this as HTMLImageElement)
        
        console.log('img onload:',img.src);
        console.dir(this)
        // 回调方法
        callback()
    }

    var exports: {
        dom: HTMLElement | null
        dom2Svg: () => any
        download: () => void
    } = {
        dom: null,
        // DOM变成svg，并作为图片显示
        dom2Svg: function () {
            var dom: HTMLElement | null = this.dom
            if (!dom) return this

            // 复制DOM节点
            var cloneDom = dom.cloneNode(true) as HTMLElement
            cloneDom.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml')
            cloneDom.classList.remove('outline')

            // 如果有图片，变成base64
            var imgDom: HTMLImageElement | null = null
            if (cloneDom.tagName.toLowerCase() == 'img') {
                imgDom = cloneDom as HTMLImageElement
            } else {
                // 这里就假设一个图片，多图自己遍历转换下就好了
                imgDom = cloneDom.querySelector('img')
            }

            if (imgDom) {
                draw(imgDom)
                imgDom.src = canvas.toDataURL()
            }

            var htmlSvg =
                'data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="' +
                dom.offsetWidth +
                '" height="' +
                dom.offsetHeight +
                '"><foreignObject x="0" y="0" width="100%" height="100%">' +
                new XMLSerializer().serializeToString(cloneDom) +
                document.querySelector('style')?.outerHTML +
                '</foreignObject></svg>'

            htmlSvg = htmlSvg
                .replace(/\n/g, '')
                .replace(/\t/g, '')
                .replace(/#/g, '%23')

            // 图片地址显示为DOM转换的svg
            img.src = htmlSvg
            
            return this
        },
        // 作为图片下载，JS前端下载可参考这篇文章：
        // JS前端创建html或json文件并浏览器导出下载 - http://www.zhangxinxu.com/wordpress/?p=6252
        download: function () {
            // 创建隐藏的可下载链接
            var eleLink = document.createElement('a')
            // 下载图片文件名就按照时间戳来
            eleLink.download =
                'zxx_png-' + (+new Date() + '').slice(1, 9) + '.png'
            eleLink.style.display = 'none'

            // 触发图片onload是个异步过程，因此，需要在回调中处理
            callback = function () {
                eleLink.href = canvas.toDataURL()
                // 触发点击
                document.body.appendChild(eleLink)
                eleLink.click()
                // 然后移除
                document.body.removeChild(eleLink)
            }

            // dom变图片
            this.dom2Svg()
        },
    }

    return exports
})()

// 实例页面的交互代码
// var eleBox = document.getElementById('cmBox')
// eleBox.addEventListener('mouseover', function (event) {
//     if (event.target !== this) {
//         event.target.classList.add('outline')
//     }
// })
// eleBox.addEventListener('mouseout', function (event) {
//     var eleOutline = eleBox.querySelector('.outline')
//     if (eleOutline) {
//         eleOutline.classList.remove('outline')
//     }
// })
// eleBox.addEventListener('click', function (event) {
//     var eleTarget = event.target
//     if (eleTarget !== this) {
//         domToImg.dom = eleTarget
//         domToImg.download()
//     }
// })
const handleClick = (payload: MouseEvent) => {
    var eleTarget = payload.target as HTMLElement
    if (eleTarget !== this) {
        domToImg.dom = eleTarget
        domToImg.download()
    }
}
</script>
<style lang="scss" scoped>
.dom-to-img {
    .dti-card {
        width: 600px;
        height: 600px;
        border: 1px solid rgba(20, 20, 20, 0.3);
        border-radius: 20px;
        overflow-y: hidden;
        img {
            width: 100%;
            height: 400px;
        }
        .dti-title {
            margin-top: 6px;
            font-size: 26px;
            font-weight: 600;
            text-shadow: 4px 4px 4px rgba(20, 20, 20, 0.3);
        }
        .dti-content {
            margin-top: 4px;
        }
    }
}
</style>
